package cn.yunyichina.provider.base.main;

import cn.yunyichina.provider.base.constant.MsgPushType;
import cn.yunyichina.provider.base.dao.OrderExceptionDao;
import cn.yunyichina.provider.base.dao.PersonalUserFamilyDao;
import cn.yunyichina.provider.base.entity.*;
import cn.yunyichina.provider.base.service.OrgService;
import cn.yunyichina.provider.base.service.impl.*;
import cn.yunyichina.provider.base.utils.CacheConstant;
import cn.yunyichina.provider.framework.common.ResponseEnum;
import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.CacheService;
import cn.yunyichina.provider.framework.dubbo.service.MessageService;
import cn.yunyichina.provider.framework.dubbo.service.impl.YytServiceImpl;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.iface.entity.ErrorCodeDefine;
import cn.yunyichina.provider.iface.entity.PersonalUser;
import cn.yunyichina.provider.iface.entity.PersonalUserOpenid;
import cn.yunyichina.provider.iface.entity.base.*;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.service.IBase;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.*;


/**
 * 基础服务子系统dubbo入口
 *
 * @author zhangkw
 * @date 2016-07-29
 */
public class BaseServiceImpl extends YytServiceImpl implements IBase {

    private static final Logger logger = LoggerFactory.getLogger(BaseServiceImpl.class);

    @Resource
    MedicalCardServiceImpl medicalCardServiceImpl;

    @Resource
    private OrgService orgService;

    @Resource
    private OrgAppServiceImpl orgAppServiceImpl;

    @Resource
    PersonalUserOpenidServiceImpl personalUserOpenidServiceImpl;

    @Resource
    PersonalUserServiceImpl personalUserServiceImpl;

    @Resource
    OrderServiceImpl orderServiceImpl;

    @Resource
    LogServiceImpl logServiceImpl;

    @Resource
    RemindSettingServiceImpl remindSettingServiceImpl;

    @Resource
    ZhyyServiceImpl zhyyServiceImpl;

    @Resource
    RuleServiceImpl ruleServiceImpl;

    @Autowired
    private OrderExceptionDao orderExceptionDao;

    @Autowired
    private PersonalUserFamilyDao personalUserFamilyDao;

    @Override
    public String getErrorCode() {

        return "1000";
    }

    @Override
    public ResCommon<List<OrgSettingVoResponse>> getOrgSettingList(OrgSettingVo vo) {
        String field = StringUtils.isNotBlank(vo.getBranchCode()) ? (vo.getHospitalCode() + ":" + vo.getBranchCode()) : vo.getHospitalCode();
        String cacheValue = null;
        if (StringUtils.isNotBlank(vo.getMethodCode())) {
            //先找带方法名的缓存
            cacheValue = CacheService.getGlobalKeyHash(CacheConstant.CACHE_BASE_MODULE, CacheConstant.CACHE_ORG_SETTING_REGION,
                    CacheConstant.CACHE_HASH_KEY, field + ":" + vo.getMethodCode());
        }
        if (StringUtils.isBlank(cacheValue)) {
            cacheValue = CacheService.getGlobalKeyHash(CacheConstant.CACHE_BASE_MODULE, CacheConstant.CACHE_ORG_SETTING_REGION,
                    CacheConstant.CACHE_HASH_KEY, field);
        }
        ResCommon<List<OrgSettingVoResponse>> resCommon;
        if (StringUtils.isNotBlank(cacheValue)) {
            resCommon = new ResCommon<>();
            List<OrgSettingVoResponse> list = new ArrayList<>();
            OrgSettingVoResponse item = JsonUtils.parseObject(cacheValue, OrgSettingVoResponse.class);
            list.add(item);
            resCommon.setResult(list);
            resCommon.setResultCodeAndMessage("0", "成功");
        } else {
            //缓存查不到，从数据库中查询并更新缓存
            OrgServiceImpl orgServiceImpl = (OrgServiceImpl) SpringContextHandler.getBean("orgServiceImpl");
            resCommon = orgServiceImpl.getOrgSettingList(vo);
            List<OrgSettingVoResponse> orgSettingList = resCommon.getResult();
            if (!CollectionUtils.isEmpty(orgSettingList)) {
                CacheService.setGlobalKeyHash(CacheConstant.CACHE_BASE_MODULE, CacheConstant.CACHE_ORG_SETTING_REGION,
                        CacheConstant.CACHE_HASH_KEY, field, JsonUtils.toJsonString(orgSettingList.get(0)));
            }
        }

        return resCommon;
    }

//    public static void main(String[] args) {
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//        BaseServiceImpl bean = applicationContext.getBean(BaseServiceImpl.class);
//
//        OrgSettingVo vo = new OrgSettingVo();
//        vo.setHospitalCode("szsrmyy");
//        vo.setBranchCode("1");
//        vo.setMethodCode("method_fenyuan2");
//        bean.getOrgSettingList(vo);
//    }

    /**
     * 更新订单数据,根据id或order_no
     * yyt.base.order.update
     * 如果包含了订单项，则会删除原来的所有订单项，然后执行新增订单项的操作
     *
     * @param data
     */
    public OrderExtVo updateOrder(String data) {
        return JsonUtils.parseObject(orderServiceImpl.updateOrder(data), OrderExtVo.class);
    }

    /**
     * 新增订单
     * yyt.base.order.add
     *
     * @param data trade_type 交易类型，1支付，2退款
     */
    public OrderExtVo addOrder(String data) {
        return JsonUtils.parseObject(orderServiceImpl.addOrder(data), OrderExtVo.class);
    }

    /**
     * 根据code查询Org
     * <br>内部调用接口
     *
     * @param data
     * @return 如果查询到1个，返回Org对象，如果没有找到或多于1个，返回null
     */
    public Org getOrgByCode(String orgCode) {
        return orgService.getOrgByCode(orgCode);
    }

    /**
     * 根据id查询org组织
     *
     * @param data
     * @return
     */
    public Response findOrgById(String orgId) {
        return orgService.findOrgById(orgId);
    }

    /**
     * 根据appCode 获得OrgApp对象
     * <br>内部调用接口
     *
     * @param orgAppCode
     * @return 如果没有找到，返回null
     */
    public OrgApp getOrgAppByAppCode(String orgAppCode) {
        return orgAppServiceImpl.getByAppCode(orgAppCode);
    }

    /**
     * 根据诊疗卡号查询用户。用于消息发送
     * yyt.base.medical.card.by.cardno.get
     *
     * @param data
     * @param orgCode
     * @param medicalCardNo
     * @param medicalCardType 卡类型\r\n            1	院内诊疗卡\r\n            2	社保卡\r\n            3	医保卡\r\n            4	区域健康卡\r\n            5	身份证\r\n            6	市民卡\r\n            7	患者唯一标识\r\n            8	临时诊疗卡\r\n            9	医疗证\r\n            10	银联卡\r\n            11	住院号
     * @param sessionid
     * @return
     */
    public MedicalCardVo getMedicalCardByCardNo(String strJson, String sessionId, String appId) {
        Response response = medicalCardServiceImpl.getMedicalCardByCardNo(strJson, sessionId, appId);
        if (!response.getResultCode().equals("0")) {
            return null;
        }
        MedicalCardVo medicalCardVo = JsonUtils.parseObject(response.getResult(), MedicalCardVo.class);
        logger.info("转换后返回的 medicalCardVo ={}", new Object[]{JsonUtils.toJsonString(medicalCardVo)});
        return medicalCardVo;
    }

    /**
     * 通用查询
     *
     * @param strJson 对应数据库字段名
     * @return
     */
    public List<PersonalUser> listPersonalUser(String strJson) {
        return personalUserServiceImpl.list(strJson);
    }

    /**
     * 查询诊疗卡
     *
     * @param strJson 对应数据库字段名
     * @return
     */
    public List<MedicalCardVo> listMedicalCard(String strJson) {
        List<MedicalCard> list = medicalCardServiceImpl.selectMedicalCard(strJson);
        List<MedicalCardVo> listVo = new ArrayList<>();
        for (MedicalCard medicalCard : list) {
            listVo.add(medicalCard);
        }
        return listVo;
    }


    /**
     * 获取openid对象
     *
     * @param userId
     * @param appId
     * @return 如果没有找到，或者参数为空的，返回null。如果找到多个，返回第一个
     */
    public PersonalUserOpenid getPersonalUserOpenid(String userId, String appId,String openId) {
        return personalUserOpenidServiceImpl.getPersonalUserOpenid(userId, appId,openId);
    }

    /**
     * 获取openid对象
     *
     * @param userId
     * @param appCode
     * @return 如果没有找到，或者参数为空的，返回null。如果找到多个，返回第一个
     */
    public PersonalUserOpenid getPersonalUserOpenidByAppCode(String userId, String appCode,String openId) {
        return personalUserOpenidServiceImpl.getPersonalUserOpenidByAppCode(userId, appCode,openId);
    }

    /**
     * 根据身份证获取用户对象
     *
     * @param idCardNo
     * @param idCardType 1：二代身份证，               2：港澳居民身份证，               3：台湾居民身份证，               4：护照
     * @return 如果没有找到，或者参数为空的，返回null。如果找到多个，返回第一个
     */
    public PersonalUser getPersonalUserByIdCardNo(String idCardNo, short idCardType) {
        return personalUserServiceImpl.getPersonalUserByIdCardNo(idCardNo, idCardType);
    }

    /**
     * 根据身份证获取用户对象
     *
     * @param mobile
     * @return 如果没有找到，或者参数为空的，返回null。如果找到多个，返回第一个
     */
    public PersonalUser getPersonalUserByMobile(String mobile) {
        return personalUserServiceImpl.getPersonalUserByMobile(mobile);
    }

    /**
     * 根据订单号orderNo获得订单
     * 内部接口
     *
     * @param orderNo
     * @return
     */
    public OrderExtVo getOrderByOrderNo(String orderNo) {
        return JsonUtils.parseObject(orderServiceImpl.getOrderByOrderNo(orderNo), OrderExtVo.class);
    }

    /**
     * 就数据库查询
     *
     * @param strJson
     * @return
     */
    public JSONArray queryZhyySql(String strJson) {
        return JsonUtils.parseArray(JsonUtils.toJsonString(zhyyServiceImpl.querySql(strJson)));

    }

    /**
     * 查询订单
     *
     * @param strJson
     * @return
     */
    public List<OrderExtVo> listOrder(String strJson) {
        List<Order> listOrder = orderServiceImpl.listOrder(strJson);
        return JsonUtils.parseArray(JsonUtils.toJsonString(listOrder), OrderExtVo.class);
    }

    public Map<String, Object> listLog(String strJson) {
        Map<String, Object> map = logServiceImpl.listLog(strJson);
        return map;

    }

    /**
     * 新增系统日志
     *
     * @param strJson LogVo对象
     * @return
     */
    public Response insertLog(String strJson) {
        return logServiceImpl.insertLog(strJson);

    }

    /**
     * 查找匹配的提醒人
     *
     * @param strJson org_id,event_code
     * @return
     */
    public List<RemindSettingVo> matchRemindSetting(String strJson) {
        List<RemindSetting> listRemind = remindSettingServiceImpl.matchRemindSetting(strJson);
        if (CollectionUtils.isNotEmpty(listRemind)) {
            List<RemindSettingVo> listReturn = new ArrayList<>();
            for (RemindSetting remindSetting : listRemind) {
                listReturn.add(JsonUtils.parseObject(remindSetting, RemindSettingVo.class));
            }
            return listReturn;
        }
        return Collections.EMPTY_LIST;
    }

    @Override
    public RuleResponseDto getRule(RuleDto ruleDto) {
        RuleResponseDto ruleResponseDto = null;
        Response response = ruleServiceImpl.selectRule(JsonUtils.toJsonString(ruleDto));
        ruleResponseDto = JsonUtils.parseObject(response.getResult(), RuleResponseDto.class);
        return ruleResponseDto;
    }

    @Override
    public void updateOrderExceptionReason(String id, String reason) {
        try {
            OrderException updateOrderException = new OrderException();
            updateOrderException.setId(id);
            updateOrderException.setExceptionReason(reason);
            orderExceptionDao.update(updateOrderException);
        } catch (RuntimeException rex) {
            logger.error("更新订单异常内容出错", rex);
        }
    }

    @Override
    public PersonalUserFamilyDto getPersonalUserFamily(String id) {
        PersonalUserFamily family = personalUserFamilyDao.selectById(id);
        PersonalUserFamilyDto familyDto = null;
        if (family != null) {
            familyDto = JsonUtils.parseObject(JsonUtils.toJsonString(family), PersonalUserFamilyDto.class);
        }
        return familyDto;
    }

    @Override
    public PersonalUserFamilyDto getPersonalUserFamilyByInsuranceName(String name) {
        PersonalUserFamilyDto familyDto = null;
        if(StringUtils.isNotBlank(name)) {
            PersonalUserFamily query = new PersonalUserFamily();
            query.setInsuranceLoginName(name);
            List<PersonalUserFamily> list = personalUserFamilyDao.select(query);
            if (list != null && list.size() > 0 ) {
                familyDto = JsonUtils.parseObject(JsonUtils.toJsonString(list.get(0)), PersonalUserFamilyDto.class);
            }
        }
        return familyDto;
    }

    @Override
    public void updatePersonalUserFamily(PersonalUserFamilyDto familyDto) {
        PersonalUserFamily family = JsonUtils.parseObject(JsonUtils.toJsonString(familyDto), PersonalUserFamily.class);
        personalUserFamilyDao.update(family);
    }

    public ResCommon<Void> patientInfoModify(PatientInfoVoOut patientInfoVoOut) {
        logger.info("BaseServiceImpl.patientInfoModify.PatientInfoVoOut request-> {}", JsonUtils.toJsonString(patientInfoVoOut));
        ResCommon<Void> resCommon = new ResCommon<>();
        if (org.springframework.util.StringUtils.isEmpty(patientInfoVoOut)) {
            logger.error("patientInfoVoOut为空或null");
            throw new CallException("-1", "patientInfoVoOut为空或null");
        }

        if (StringUtils.isEmpty(patientInfoVoOut.getPatId()) || StringUtils.isEmpty(patientInfoVoOut.getHospitalCode())) {
            resCommon.setResultCodeAndMessage(
                    ResponseEnum.Common.PARAMETRE_ERR.getCode(),
                    ResponseEnum.Common.PARAMETRE_ERR.getMessage()
            );
            return resCommon;
        }
        try {
            MedicalCard medicalCard = new MedicalCard();
            medicalCard.setHisPatId(patientInfoVoOut.getPatId());
            medicalCard.setPatName(patientInfoVoOut.getPatientName());
            medicalCard.setMedicalCardType(patientInfoVoOut.getCardType());
            medicalCard.setMedicalCardNo(patientInfoVoOut.getCardNo());
            String medicalCardStr = JsonUtils.toJsonString(medicalCard);
            logger.info("BaseServiceImpl.patientInfoModify.medicalCard request-> {}", medicalCardStr);
            medicalCardServiceImpl.updatePatientInfoByPatId(medicalCardStr);
        } catch (Exception e) {
            logger.error("数据查询异常[BaseServiceImpl.patientInfoModify]", e);
            resCommon.setResultCodeAndMessage(
                    ResponseEnum.Common.FAILURE.getCode(),
                    ResponseEnum.Common.FAILURE.getMessage()
            );
            return resCommon;
        }
        return resCommon;
    }

    @Override
    public ResCommon<Void> templateMsgPush(MsgPushVoOut msgPushVoOut) {
        logger.info("BaseServiceImpl.templateMsgPush.msgPushVoOut request-> {}", JsonUtils.toJsonString(msgPushVoOut));
        ResCommon<Void> resCommon = new ResCommon<>();
        JSONObject medicalParam = new JSONObject();
        if (org.springframework.util.StringUtils.isEmpty(msgPushVoOut)) {
            logger.error("msgPushVoOut为空或null");
            throw new CallException("-1", "msgPushVoOut为空或null");
        }
        if (checkMsgPushVoOutParameters(msgPushVoOut)) {
            resCommon.setResultCodeAndMessage(
                    ResponseEnum.Common.PARAMETRE_ERR.getCode(),
                    ResponseEnum.Common.PARAMETRE_ERR.getMessage()
            );
            return resCommon;
        }
        try {
            Map<String, Object> dataMap = new HashedMap();
            Short userType = checkUserType(msgPushVoOut.getUserType());
            if (userType == null) {
                resCommon.setResultCodeAndMessage(
                        ResponseEnum.Common.PARAMETRE_ERR.getCode(),
                        ResponseEnum.Common.PARAMETRE_ERR.getMessage()
                );
                return resCommon;
            } else {
                dataMap.put("user_type", userType);
            }
            dataMap.put("to_user", msgPushVoOut.getToUser());
            if (userType == 1) {
                medicalParam.put("card_no", msgPushVoOut.getToUser());
                medicalParam.put("app_id", msgPushVoOut.getAppId());
                logger.debug("yyt.base.medicalcard.by.cardno.and.appid.get请求：" + JsonUtils.toJsonString(medicalParam));
                MedicalCard medicalCard = medicalCardServiceImpl.getMedicalcardByCardnoAndAppid(JsonUtils.toJsonString(medicalParam));
                if (medicalCard == null) {
                    throw new CallException(ErrorCodeDefine.MESSAGE_NOT_USER, "无此用户");
                }
                logger.debug("yyt.base.medicalcard.by.cardno.and.appid.get返回：" + JsonUtils.toJsonString(medicalCard));
                dataMap.put("org_app_code", medicalCard.getBindSourceAppCode());
            } else if (userType == 2) {
                medicalParam.put("open_id", msgPushVoOut.getToUser());
                logger.debug("yyt.base.medicalcard.by.openid.get请求：" + JsonUtils.toJsonString(medicalParam));
                MedicalCard medicalCard = medicalCardServiceImpl.getMedicalCardById(JsonUtils.toJsonString(medicalParam));
                if (medicalCard == null) {
                    throw new CallException(ErrorCodeDefine.MESSAGE_NOT_USER, "无此用户");
                }
                logger.debug("yyt.base.medicalcard.by.openid.get返回：" + JsonUtils.toJsonString(medicalCard));
                dataMap.put("org_app_code", medicalCard.getBindSourceAppCode());
            } else if (userType == 3) {
                dataMap.put("order_no", msgPushVoOut.getToUser());
                Map<String, String> map = new HashMap<String, String>();
                map.put("order_no", msgPushVoOut.getToUser());
                Response ordResponse = BaseService.callUnderlineFromInternal("yyt.base.order.by.order.no.out.get",
                        JsonUtils.toJsonString(map));
                logger.info("BaseServiceImpl.templateMsgPush, ordResponse request=" + JSONObject.toJSONString(ordResponse));
                if (!"0".equals(ordResponse.getResultCode())) {
                    logger.info("BaseServiceImpl.templateMsgPush, 查询订单失败。");
                    resCommon.setResultCodeAndMessage("0", "查询订单失败。");
                    return resCommon;
                }
                OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);
                if (order == null) {
                    logger.error("查询订单为空 订单号=" + msgPushVoOut.getToUser() + ",ordResponse=" + JSON.toJSONString(ordResponse));
                    resCommon.setResultCodeAndMessage("0", "查询订单失败。");
                    return resCommon;
                }
                dataMap.put("org_app_code", order.getPlatformOrgAppCode());
            }
            if (msgPushVoOut.getPlatformType() == 1) {
                dataMap.put("platform_type", "1");
            } else if (msgPushVoOut.getPlatformType() == 2) {
                dataMap.put("platform_type", "2");
            }
            dataMap.put("org_code", msgPushVoOut.getHospitalCode());
            dataMap.put("template_code", "22000");
            dataMap.put("msg_content", JsonUtils.toJsonString(msgPushVoOut.getMsgContent()));
            dataMap.put("url", msgPushVoOut.getUrl());
            dataMap.put("app_id", msgPushVoOut.getAppId());
            logger.info("消息推送对外接口templateMsgPush, 请求：调用message模块, request={}", JsonUtils.toJsonString(dataMap));
            Response messageResponse = MessageService.callHumpFromInternal("yyt.message.msg.template.send", JsonUtils.toJsonString(dataMap));
            logger.info("消息推送对外接口templateMsgPush, 返回：调用message模块, response={}", JsonUtils.toJsonString(messageResponse));
        } catch (Exception e) {
            logger.error("消息推送对外接口templateMsgPush异常[BaseServiceImpl.templateMsgPush]", e);
            resCommon.setResultCodeAndMessage(
                    ResponseEnum.Common.FAILURE.getCode(),
                    ResponseEnum.Common.FAILURE.getMessage()
            );
            return resCommon;
        }
        return resCommon;
    }

    private boolean checkMsgPushVoOutParameters(MsgPushVoOut request) {
        if (StringUtils.isEmpty(request.getHospitalCode()) ||
                StringUtils.isEmpty(request.getPlatformType() == null ? "" : request.getPlatformType().toString()) ||
                StringUtils.isEmpty(request.getUserType() == null ? "" : request.getUserType().toString()) ||
                StringUtils.isEmpty(request.getToUser()) ||
                StringUtils.isEmpty(request.getTemplateCode()) ||
                StringUtils.isEmpty(request.getMsgContent()) || StringUtils.isEmpty(request.getAppId())) {
            return true;
        }

        return false;
    }

    private Short checkUserType(Short userType) {
        if (userType == MsgPushType.MEDICAL_CARD) {
            return Short.valueOf("1");
        } else if (userType == MsgPushType.OPEN_ID) {
            return Short.valueOf("2");
        } else if (userType == MsgPushType.REGISTER || userType == MsgPushType.CLINIC || userType == MsgPushType.DEPOSIT) {
            return Short.valueOf("3");
        }
        return null;
    }

}
